package com.chucang.shucang.common.security.service;

import cn.hutool.core.collection.CollUtil;
import com.chucang.shucang.common.base.constant.CacheConstant;
import com.chucang.shucang.common.base.constant.SecurityConstant;
import com.chucang.shucang.common.base.utils.R;
import com.chucang.shucang.common.security.feign.BacUserDetailService;
import com.chucang.shucang.common.security.entity.ShuCangUser;
import com.chucang.shucang.common.security.feign.vo.BacUserInfoVO;
import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cache.Cache;
import org.springframework.cache.CacheManager;
import org.springframework.context.annotation.Primary;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.userdetails.UserDetails;

import java.util.*;

/**
 * @author flitsneak
 * @email flitsneak@gmail.com
 * @date 2022/10/18 15:39
 * @description 管理端密码模式登录
 */
@Slf4j
@Primary
@RequiredArgsConstructor
public class ShuCangBacPwdUserDetailsServiceImpl implements ShuCangUserDetailsService {

    private final BacUserDetailService bacUserDetailService;

    private final CacheManager cacheManager;

    /**
     * 账号密码登录
     *
     * @param username 用户名
     * @return 用户信息
     */
    @Override
    @SneakyThrows
    public UserDetails loadUserByUsername(String username) {
        Cache cache = cacheManager.getCache(CacheConstant.USER_DETAILS);
        if (cache != null && cache.get(username) != null) {
            return (ShuCangUser) Objects.requireNonNull(cache.get(username)).get();
        }

        R<BacUserInfoVO> result = bacUserDetailService.getManagerInfoByUsername(username, SecurityConstant.FROM_IN);
        BacUserInfoVO managerInfo = result.getData();
        Set<String> dbAuthsSet = new HashSet<>();
        if (!CollUtil.isEmpty(managerInfo.getRoles())) {
            // 获取角色
            managerInfo.getRoles().forEach(role -> dbAuthsSet.add(SecurityConstant.ROLE + role));
            // 获取资源
            dbAuthsSet.addAll(managerInfo.getMenuCodes());
        }

        Collection<GrantedAuthority> authorities = AuthorityUtils
                .createAuthorityList(dbAuthsSet.toArray(new String[0]));

        if (cache != null) {
            cache.put(username, new ShuCangUser(managerInfo.getUserId(), managerInfo.getUsername(), SecurityConstant.NOOP + managerInfo.getPassword(), managerInfo.getCellPhoneNum(), managerInfo.getUsername(), 0, null, true, true, true, true, authorities));
        }
        return new ShuCangUser(managerInfo.getUserId(), managerInfo.getUsername(), SecurityConstant.NOOP + managerInfo.getPassword(), managerInfo.getCellPhoneNum(), managerInfo.getUsername(), 0, null, true, true, true, true, authorities);
    }

    /**
     * 校验token时 使用
     *
     * @param shuCangUser user
     * @return u
     */
    @Override
    public UserDetails loadUserByUser(ShuCangUser shuCangUser) {
        return this.loadUserByUsername(shuCangUser.getUsername());
    }

    /**
     * 是否支持此客户端校验
     *
     * @param clientId 目标客户端
     * @return true/false
     */
    @Override
    public boolean support(String clientId, String grantType) {
        return SecurityConstant.BAC_PWD.equals(clientId);
    }

}
